﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.Registrator;
using System.Drawing;
using System.ComponentModel;
using DevExpress.XtraTreeList;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using System.Windows.Forms;
using DevExpress.Utils;
using System.Collections;
using DevExpress.XtraTreeList.Nodes;
using DevExpress.Data;
using DevExpress.XtraGrid.Helpers;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid;

namespace SAF.Controls
{
    [UserRepositoryItem("RegisterTreeLookUpEdit")]
    public class RepositoryItemTreeLookUpEdit : RepositoryItemLookUpEditBase
    {
        private TreeList tree;

        private bool showClearButton = true;
        TreeLookUpEditPopup lookUpPopup;

        static RepositoryItemTreeLookUpEdit()
        {
            RegisterTreeLookUpEdit();
        }

        public RepositoryItemTreeLookUpEdit()
        {
            this.showClearButton = true;
            this.NullText = string.Empty;
            this.tree = CreateTree();
            this.QueryPopUp += new CancelEventHandler(RepositoryItemTreeLookUpEdit_QueryPopUp);
        }

        void RepositoryItemTreeLookUpEdit_QueryPopUp(object sender, CancelEventArgs e)
        {
            if (this.OwnerEdit.EditValue != null && this.OwnerEdit.EditValue != DBNull.Value)
            {
                var node = this.tree.FindNodeByKeyID(this.OwnerEdit.EditValue.ToString());
                this.Tree.FocusedNode = node;
            }
        }

        private TreeList CreateTree()
        {
            var ctl = new TreeList();
            ctl.OptionsBehavior.Editable = false;
            return ctl;
        }

        public override void BeginInit()
        {
            Tree.BeginInit();
            base.BeginInit();
        }
        public override void EndInit()
        {
            Tree.EndInit();
            base.EndInit();
        }

        [Category("Data")]
        public virtual string ParentFieldName { get; set; }

        protected internal TreeList Tree { get { return tree; } }

        public virtual void PopulateViewColumns()
        {
            if (Tree.Columns.Count > 0 || this.DataSource == null) return;

            Tree.PopulateColumns();
        }

        public static void RegisterTreeLookUpEdit()
        {
            Image img = null;
            EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo("TreeLookUpEdit", typeof(TreeLookUpEdit), typeof(RepositoryItemTreeLookUpEdit),
                typeof(TreeLookUpEditViewInfo), new DevExpress.XtraEditors.Drawing.ButtonEditPainter(), true, img,
                typeof(DevExpress.Accessibility.PopupEditAccessible)));
        }

        [Category("Behavior"), DefaultValue(true)]
        public bool ShowClearButton
        {
            get { return showClearButton; }
            set
            {
                if (ShowClearButton == value) return;
                showClearButton = value;
                OnPropertiesChanged();
            }
        }

        [Category(CategoryName.Behavior), DefaultValue(TextEditStyles.DisableTextEditor)]
        public override TextEditStyles TextEditStyle
        {
            get { return base.TextEditStyle; }
            set
            {
                if (value == TextEditStyles.Standard) value = TextEditStyles.DisableTextEditor;
                base.TextEditStyle = value;
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TreeLookUpEdit OwnerEdit
        {
            get
            {
                return base.OwnerEdit as TreeLookUpEdit;
            }
        }

        [Description("Gets the class name of the current editor.")]
        public override string EditorTypeName
        {
            get
            {
                return "TreeLookUpEdit";
            }
        }

        internal Size GetDesiredPopupFormSizeCore(bool forceMinSize)
        {
            return base.GetDesiredPopupFormSize(forceMinSize);
        }


        internal void SetupLookUpPopup()
        {
            if (lookUpPopup != null) return;
            if (Tree == null) return;
            lookUpPopup = CreateLookUpPopup();
            lookUpPopup.SetupTree(Tree);
        }

        protected virtual void OnControllerListChanged(object sender, ListChangedEventArgs e)
        {
            this.ResetValuesCache(true);
        }

        protected internal virtual void ResetValuesCache(bool fireRefresh)
        {
            if (this.OwnerEdit != null)
            {
                if (fireRefresh)
                {
                    this.OwnerEdit.RefreshCore(false);
                }
            }
        }

        protected virtual BaseGridController CreateDataControllerInstance()
        {
            return new GridDataController();
        }

        protected virtual TreeLookUpEditPopup CreateLookUpPopup()
        {
            return new TreeLookUpEditPopup(this);
        }

        protected internal TreeLookUpEditPopup LookUpPopup
        {
            get
            {
                if (lookUpPopup == null)
                {
                    SetupLookUpPopup();
                }
                return lookUpPopup;
            }
        }

        internal void ActivateDataSource()
        {
            if (this.Tree.DataSource != base.DataSource)
            {
                try
                {
                    this.Tree.DataSource = null;
                    this.Tree.BindingContext = new BindingContext();
                    this.Tree.DataSource = this.DataSource;
                    this.Tree.KeyFieldName = base.ValueMember;
                    this.Tree.ParentFieldName = ParentFieldName;
                    this.ResetValuesCache();
                }
                finally
                {

                }
            }
        }

        protected override void OnLoaded()
        {
            if (this.OwnerEdit != null && this.OwnerEdit.IsHandleCreated)
            {
                this.ActivateDataSource();
            }
            base.OnLoaded();
        }



        protected internal void ResetValuesCache()
        {
            this.ResetValuesCache(false);
        }

        public override string GetDisplayText(FormatInfo format, object editValue)
        {
            if (this.OwnerEdit != null && !this.OwnerEdit.IsDisplayTextValid)
            {
                if (this.TextEditStyle == TextEditStyles.Standard)
                {
                    return this.OwnerEdit.AutoSearchText;
                }
                return base.GetDisplayText(format, editValue);
            }
            else
            {
                if (base.DataSource == null && !this.IsNullValue(editValue))
                {
                    return this.GetNullEditText();
                }
                if (this.IsNullValue(editValue))
                {
                    return base.GetDisplayText(format, editValue);
                }
                string displayTextByKeyValue = this.GetDisplayTextByKeyValue(editValue);
                if (displayTextByKeyValue == null)
                {
                    return string.Empty;
                }
                return displayTextByKeyValue;
            }
        }

        public override void Assign(RepositoryItem item)
        {
            RepositoryItemTreeLookUpEdit repositoryItemTreeLookUpEdit = item as RepositoryItemTreeLookUpEdit;
            this.BeginUpdate();
            try
            {
                this.Tree.DataSource = null;
                base.Assign(item);
                if (repositoryItemTreeLookUpEdit != null)
                {
                    this.ActivateDataSource();
                }
            }
            finally
            {

                this.EndUpdate();
            }
        }

        protected override void OnDataSourceChanged()
        {
            if (!this.IsLoading)
            {
                this.ActivateDataSource();
            }
            base.OnDataSourceChanged();
        }

        private Hashtable displayCache = new Hashtable();

        public virtual string GetDisplayTextByKeyValue(object keyValue)
        {
            string text = string.Empty;
            if (keyValue == null || this.IsNullValue(keyValue))
            {
                text = this.NullText;
            }
            else
            {
                text = this.displayCache[keyValue.ToString()] as string;
                if (text == null)
                {

                    var node = this.GetNodeByKeyValue(keyValue.ToString());
                    if (node != null)
                    {
                        text = node.GetDisplayText(this.DisplayMember);
                        this.displayCache[keyValue.ToString()] = text;
                    }
                    else
                    {
                        text = string.Empty;
                    }
                }
            }
            CustomDisplayTextEventArgs customDisplayTextEventArgs = new CustomDisplayTextEventArgs(keyValue, text);
            this.RaiseCustomDisplayText(customDisplayTextEventArgs);
            return customDisplayTextEventArgs.DisplayText;
        }

        public TreeListNode GetNodeByKeyValue(object keyValue)
        {
            var node = this.Tree.FindNodeByKeyID(keyValue);
            return node;
        }


        internal int FindItem(string text, bool partial)
        {
            var node = this.Tree.FindNodeByFieldValue(this.DisplayMember, text);
            if (node != null)
            {
                return this.tree.Nodes.IndexOf(node);
            }
            else
            {
                return -1;
            }
        }

        internal void ClearClick()
        {
            if (this.OwnerEdit != null && this.OwnerEdit.IsPopupOpen)
            {
                this.OwnerEdit.CancelPopup();
                this.OwnerEdit.EditValue = null;
            }
        }
    }
}
